from sympy import gamma as _gamma
from math import sqrt as _sqrt
from ..ess import tryget as _tryget
e: float = 2.718281828459045
Pi: float = 3.141592653589793
inf: float = float("inf")


def isprime(x: int) -> bool:
    """判断质数"""
    return False if x < 2 else all(x % i for i in range(2, int(_sqrt(x))+1))


def GaussNum(b, n):
    """求出高斯质因数分解数"""
    return 1 if b % 2 == 0 else (n+1) % 2 if b % 4-1 else n+1


def upint(nun, base=1) -> int:
    """找到大于num的第一个base的倍数"""
    return int(nun // base*base) + base if nun % base else 0


def isInteger(x: float) -> bool:
    """判断是否为整数"""
    if isinstance(x, int):
        return True
    elif isinstance(x, float):
        return x.is_integer()
    else:
        return False


def signof(n) -> int:
    """符号函数"""
    return int(n/abs(n)) if n else 0


def Riemann(x=1):
    """黎曼泽塔函数"""
    o = 1
    for i in range(2, 10000):
        ans = i**(-x)
        if ans <= 10**(-15):
            break
        o += ans
    return o


'''def GaussCir(r2):
    """一个R方为r2的圆所经过的高斯整数个数"""
    if r2 == 1:
        return 4
    else:
        return 4*dolist(lambda x, y: x*y, [GaussNum(i, j) for i, j in freqSort(PrimeFactorDec(r2))])'''


def PrimeFactorDec(x):
    """质因数分解"""
    o = []
    for i in range(2, x+1):
        while x % i == 0:
            x //= i
            o.append(i)
        if x == 1:
            break
    return o


def FFactorial(x: float) -> float:
    """浮点数阶乘"""
    return _gamma(x+1)

def Factorial(x: int) -> int:
    """阶乘"""
    o = 1
    for i in range(1, x+1):
        o *= i
    return o


def DoubleFactorial(x):
    """双阶乘"""
    o = 1
    for i in range(x, 0, -2):
        o *= i
    return o


def Convol(l1, l2, n):
    """卷积"""
    return sum(_tryget(l1, i)*_tryget(l2, n-i) for i in range(n+1))


def PolynomialMultiplication(l1, l2):
    """多项式乘法"""
    return [Convol(l1, l2, i) for i in range(len(l1)+len(l2)-1)]


def EvalMultiplication(lst, x):
    """多项式求值"""
    leng = len(lst)
    if leng == 1:
        return lst[0]
    elif leng == 0:
        return 0
    x2 = x**2
    l0 = [lst[i] for i in range(leng) if not i % 2]
    l1 = [lst[i] for i in range(leng) if i % 2]
    return EvalMultiplication(l0, x2)+x*EvalMultiplication(l1, x2)


def Euclidean(a: int, b: int) -> int:
    """辗转相除法计算两个非负整数a，b的最大公约数"""
    a, b = (a, b) if a >= b else (b, a)
    if not b:
        return 0
    while b:
        a, b = b, a % b
    return a


def LeastCommonMultiple(a: int, b: int) -> int:
    """求取最小公倍数"""
    return a*b//Euclidean(a, b)


def isRelativelyPrime(a: int, b: int) -> bool:
    """判断互素"""
    return Euclidean(a, b) == 1


class feibonacci():
    """斐波那契数列迭代器"""

    def __init__(self, n) -> None:
        self.n = n

    def __iter__(self):
        i, a, b = 0, 0, 1
        while(i < self.n):
            num = b
            a, b = b, a+b
            i += 1
            yield num
